var generator = require("../generator");
var validator = require("../validator");
var minitor = require("./minitor");
var mediator = require("./mediator");
var CommunicationStateEnum = require("./enum");

exports.minitor = minitor;
exports.mediator = mediator;

/**
 * 执行网络请求
 * @param {请求地址} url
 * @param {请求参数} data
 * @param {请求配置} options
 */
exports.request = (url, data = {}, options = {}) => {
  var method = options.method ? options.method : "post",
    options = {
      method: method,
      loading: options.loading == false ? false : true,
      loadingText: options.loadingText ? options.loadingText : "加载中...",
      contentType: options.contentType
        ? options.contentType
        : "application/json",
      failshowToast: options.failshowToast == false ? false : true,

      /**
       * 是否为必要请求
       * @discuss：1、necessary 请求表示如果该次请求失败，则弹出提示框，
       *             阻止界面上的下一步操作，来保证业务流程的正确性
       *           2、常用语页面初始化失败的处理
       *           3、默认get为necessary请求，如在options中指定了necessary, 则以该options.necessary为准
       * */
      necessary: options.necessary == undefined ? false : options.necessary,

      /**
       * 不要求权限验证
       */
      tokenIgnore:
        options.tokenIgnore == undefined ? false : options.tokenIgnore,
    };

  return new Promise(function (_success, _fail) {
    // 生成请求唯一表示 uuid
    var uuid = generator.UUID();
    requestManager.put(uuid, {
      url,
      data,
      options,
      _success,
      _fail,
    });

    // 执行网络请求
    doRequest(uuid);
  });
};

function HashMap() {
  this.map = {};
}
HashMap.prototype = {
  put: function (key, value) {
    // 向Map中增加元素（key, value)
    this.map[key] = value;
  },
  get: function (key) {
    //获取指定Key的元素值Value，失败返回Null
    if (this.map.hasOwnProperty(key)) {
      return this.map[key];
    }
    return null;
  },
  remove: function (key) {
    // 删除指定Key的元素，成功返回True，失败返回False
    if (this.map.hasOwnProperty(key)) {
      return delete this.map[key];
    }
    return false;
  },
  removeAll: function () {
    //清空HashMap所有元素
    this.map = {};
  },
  keySet: function () {
    //获取Map中所有KEY的数组（Array）
    var _keys = [];
    for (var i in this.map) {
      _keys.push(i);
    }
    return _keys;
  },
};

HashMap.prototype.constructor = HashMap;

// 请求管理对象
var requestManager = new HashMap();

// 请求失败列表
var requestFailList = new Array();

/**
 * 执行网络请求
 */
function doRequest(uuid) {
  // 检查当前网络状况
  wx.getNetworkType({
    success(res) {
      // 无网络或只有2g信号的时候, 提示网络错误
      if (res.networkType == "none" || res.networkType == "2g") {
        // 加入到请求失败列表
        requestFailList.push([
          uuid,
          { errMsg: "网络不稳定，当前信号为【" + res.networkType + "】" },
        ]);

        // 显示网络错误
        mediator.showNetWorkError(
          networkTypeDesc(res.networkType),
          retryFailedRequest,
          giveUpFailedRequest
        );

        // 通知请求监控者，网络异常
        minitor.notifyStateChanged(
          CommunicationStateEnum.COMMUNICATION_STATE_NETWORK_ERROR,
          requestManager.get(uuid)
        );
      } else {
        // 获取请求信息
        var { url, data, options, _success, _fail } = requestManager.get(uuid);

        if (options.loading) {
          wx.showLoading({
            title: options.loadingText,
            mask: true,
          });
        }

        // 通知请求监控者，已经开启通讯
        minitor.notifyStateChanged(
          CommunicationStateEnum.COMMUNICATION_STATE_COMMUNICATING,
          requestManager.get(uuid)
        );

        // 发送请求
        wx.request({
          url: url,
          data: data,
          method: options.method,
          header: {
            "Content-type": options.contentType,
            Authorization: "Bearer " + mediator.getToken(),
          },
          success: function (res) {
            // 服务端正常返回

            console.log(res.data, "\nurl:" + url + "\ndata:", data);

            // 未登录处理
            if (mediator.shouldReLogin(res)) {
              // 通知请求监控者，未登录
              minitor.notifyStateChanged(
                CommunicationStateEnum.COMMUNICATION_STATE_NO_LOGIN,
                requestManager.get(uuid),
                res
              );

              // 从请求的集合中删除
              requestManager.remove(uuid);

              // 弹出登录界面
              mediator.showLoginError();

              return;
            }

            if (
              (res.data.status >= 200 && res.data.status <= 300) ||
              (res.data.code <= 300 && res.data.code >= 200)
            ) {
              // 请求成功的处理
              succeedResultHandle(res, _success, uuid);
            } else {
              // logJS.info(JSON.stringify(res) + '--------url:' + url + '----------data:' + JSON.stringify(data))

              // 请求失败处理
              failResultHandle(options, res, _fail, uuid);
            }
          },
          fail: function (err) {
            console.log(err, "\nfailurl=>:" + url + "\ndata:", data);

            // 请求失败处理
            failResultHandle(options, res, _fail, uuid);
          },
          complete: function () {
            if (requestFailList.length > 0) {
              console.log(
                "-----------------------------------------------------"
              );
              console.log("当前未完成请求列表：");
              console.log(requestManager);
              console.log(
                "-----------------------------------------------------"
              );
              console.log("当前请求失败列表：");
              console.log(requestFailList);
            }

            if (options.loading) {
              wx.hideLoading();
            }
          },
        });
      }
    },
  });
}

/**
 * 请求成功处理
 */
function succeedResultHandle(res, _success, uuid) {
  // 请求成功
  minitor.notifyStateChanged(
    CommunicationStateEnum.COMMUNICATION_STATE_SUCCEED,
    requestManager.get(uuid),
    res
  );

  if (validator.isFunction(_success)) {
    // 返回请求成功
    _success(res.data);
  }

  // 从请求的集合中删除
  requestManager.remove(uuid);
}

/**
 * 处理服务端code
 */
function renderTitle(item) {
  const TEXT = "服务器";
  if (item.data.msg) {
    return item.data.msg;
  }
  if (item.data.status) return `${TEXT}${item.data.status}`;
  if (item.data.code) return `${TEXT}${item.data.code}`;
  if (item.statusCode) return `${TEXT}${item.statusCode}`;
  return JSON.stringify(item);
}

/**
 * 请求失败处理
 */
function failResultHandle(options, res, _fail, uuid) {
  // 通知请求监控者---通讯失败
  minitor.notifyStateChanged(
    CommunicationStateEnum.COMMUNICATION_STATE_FAILED,
    requestManager.get(uuid),
    res
  );

  if (options.necessary) {
    // 如果是必要请求
    // 加入到请求失败列表
    requestFailList.push([uuid, res]);

    // 显示系统错误
    mediator.showSytemError(retryFailedRequest, giveUpFailedRequest);
  } else if (getApp().globalData.isRequestErrorVisible != true) {
    // 非必要请求失败处理

    if (options.failshowToast) {
      // 是否要显示系统返回信息
      setTimeout(() => {
        wx.showToast({
          icon: "none",
          title: renderTitle(res),
        });
        setTimeout(() => {
          wx.hideToast();
        }, 1500);
      }, 0);
    }

    // 返回请求失败
    if (_fail != null && validator.isFunction(_fail)) {
      _fail(res);
    }

    // 从请求的集合中删除
    requestManager.remove(uuid);
  }
}

/**
 * 重新发送失败的请求
 */
function retryFailedRequest() {
  var failedList = requestFailList;

  // 清空之前的请求失败列表
  requestFailList = new Array();

  failedList.map((data) => {
    var uuid = data[0];

    doRequest(uuid);
  });
}

/**
 * 稍后再试
 */
function giveUpFailedRequest() {
  var failedList = requestFailList;

  // 清空之前的请求失败列表
  requestFailList = new Array();

  failedList.map((data) => {
    var uuid = data[0];

    var { _fail } = requestManager.get(uuid);

    // 返回错误
    if (_fail != null && validator.isFunction(_fail)) {
      _fail({
        errMsg: "",
      });
    }
    wx.navigateBack({});
  });
}

/**
 * 网络状态描述
 */
function networkTypeDesc(networkType) {
  if (networkType == "wifi") {
    return "wifi 网络";
  } else if (networkType == "2g") {
    return "2g 网络";
  } else if (networkType == "3g") {
    return "3g 网络";
  } else if (networkType == "4g") {
    return "4g 网络";
  } else if (networkType == "5g") {
    return "5g 网络";
  } else if (networkType == "none") {
    return "无网络";
  } else if (networkType == "unknown") {
    return "Android 下不常见的网络类型";
  }
}
